package com.atguigu.gmall.realtime.common.util;

import com.atguigu.gmall.realtime.common.bean.TableProcessDim;
import com.atguigu.gmall.realtime.common.constant.Constant;
import com.google.common.base.CaseFormat;
import org.apache.commons.beanutils.BeanUtils;
import org.codehaus.jackson.map.util.BeanUtil;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcUtil {
    public static Connection getConnection(){
        try {
            // 1.注册启动
            Class.forName(Constant.MYSQL_DRIVER);
            // 2.获取连接
            java.sql.Connection connection = DriverManager.getConnection(Constant.MYSQL_URL, Constant.MYSQL_USER_NAME, Constant.MYSQL_PASSWORD);
            return connection;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("获取 Mysql连接失败");
        }

    }

    public static void closeConnection(Connection connection){
        try {
            if (connection != null && ! connection.isClosed()){
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("关闭Mysql连接失败");
        }
    }

    public static void main(String[] args) {
        Connection connection = getConnection();
        String sql = "select source_table, sink_table, sink_family, sink_columns, sink_row_key " +
                "from gmall2024_config_240228.table_process_dim " +
                "where source_table = 'user_info'";
        // List<TableProcessDim> tableProcessDimList = queryList(connection, sql, TableProcessDim.class, true);
        // tableProcessDimList.forEach(System.out::println);
        TableProcessDim tableProcessDim = queryOne(connection, sql, TableProcessDim.class, true);
        System.out.println(tableProcessDim);
        closeConnection(connection);
    }

    /**
     * 通用查询
     * 查询多条数据
     */
    public static <T> List<T> queryList(Connection connection, String sql, Class<T> returnType, Boolean isUnderToCamel){
        ArrayList<T> list = new ArrayList<>();

        try {
            // 3. 编写sql

            // 4. 编译sql
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            // 5. 执行sql
            ResultSet resultSet = preparedStatement.executeQuery();
            // 6. 处理结果集
            while (resultSet.next()) {

                // 通过反射的方式创T对象
                // 要求T类中提供无参构造器
                T t = returnType.newInstance();

                // 如果没有提供无参数构造器, 只能获取带参数的构造器
                // Constructor<T> constructor = returnType.getDeclaredConstructor(String.class, Integer.class);
                // T t = constructor.newInstance("zhangsan", 20);

                // 从结果集中提取元数据
                ResultSetMetaData metaData = resultSet.getMetaData();
                // 提取结果集的列个数
                int columnCount = metaData.getColumnCount();
                // 循环获取每个列名
                // TODO JDBC的下标操作都是从1开始的
                for (int i = 1; i <= columnCount; i++) {
                    // 获取列名
                    String columnLabel = metaData.getColumnLabel(i);
                    // 获取列值
                    Object columnValue = resultSet.getObject(columnLabel);

                     // 约定: 结果集中的列名 与 对象的属性名相同, 或者遵循 下划线到驼峰的映射规则
                    //      结果集的列: sourceTable  对象的属性名:sourceTable
                    //      结果集的列: source_table  对象的属性名:sourceTable
                    if (isUnderToCamel){
                        // 将下划线的形式 转换成 驼峰的形式
                        columnLabel = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, columnLabel);
                    }

                    // 反射
                    // 基于属性对象完成
                    // Field declaredField = t.getClass().getDeclaredField(columnLabel);
                    // declaredField.set(t, columnValue);

                    // 基于方法对象完成
                    // sourceTable -> setSourceTable
                    // String methodName = "setSourceTable";
                    // Method declaredMethod = t.getClass().getDeclaredMethod(methodName, declaredField.getType());
                    // declaredMethod.invoke(t, columnValue);


                    // 使用第三方工具的方法
                    BeanUtils.copyProperty(t, columnLabel, columnValue);

                }

                list.add(t);
            }
            // 7. 返回结果
            return list;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("查询Mysql数据失败");
        }
    }

    /**
     * 查询单条数据
     */
    public static <T> T queryOne(Connection connection, String sql, Class<T> returnType, Boolean isUnderToCamel){
        List<T> list = queryList(connection, sql, returnType, isUnderToCamel);
        if (list.size()!=0){
            return list.get(0);
        }

        return null;
    }
}
